Bash - Les arguments (paramètres) et la commande getopts

Les arguments (paramètres)

Il est possible de fournir à un script, sur la ligne de commandes, les arguments nécessaires à son exécution. Ces arguments sont appelés "paramètres".
Il en existe deux catégories : les paramètres positionnels et les paramètres spéciaux.

Table des matières

Les arguments (paramètres)

Paramètres positionnels

Exemple 1

Les paramètres spéciaux

Exemple 2

Initialiser des paramètres

- La commande "set" -

Exemples

- La commande "shift" -

Exemple 3

Getopts

Ajouter des options avec getop

contrôle les opérateurs utilisés par une commande

 

Paramètres positionnels

Ce sont tous simplement les arguments passés en "paramètres" sur la ligne de commandes, à l'invocation d'un script. Ils sont alors affectés aux variables réservées 1,2,3,...9,10,11,... et peuvent être appelés à l'aide des expressions

$1

,

$2

...

${10}

,

${11}

...
Note : Le shell Bourne est limité aux paramètres de 0 à 9.

Exemple 1

Voici un petit script qui se contente d'afficher certains des arguments passés en paramètres en fonction de leur position.

#!/bin/bash

# affiche_param.sh

 

echo "Le 1er paramètre est : $1"

echo "Le 3ème paramètre est : $3"

echo "Le 10ème paramètre est : ${10}"

echo "Le 15ème paramètre est : ${15}"

Il suffit alors d'invoquer le script en lui passant un certain nombre de paramètres :

./affiche_param.sh 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Le 1er paramètre est : 1

Le 3ème paramètre est : 3

Le 10ème paramètre est : 10

Le 15ème paramètre est : 15

ou encore :

./affiche_param.sh un 2 trois 4 5 6 7 8 9 dix 11 12 13 14 quinze 16 17

Le 1er paramètre est : un

Le 3ème paramètre est : trois

Le 10ème paramètre est : dix

Le 15ème paramètre est : quinze

Si certains paramètres contiennent des caractères spéciaux ou des espaces, il
faut alors les "quoter" :

./affiche_param.sh un 2 "le 3ème" 4 5 6 7 8 9 dix 11 12 13 14 "le 15ème" 16 17

Le 1er paramètre est : un

Le 3ème paramètre est : le 3ème

Le 10ème paramètre est : dix

Le 15ème paramètre est : le 15ème

Les paramètres spéciaux

Ce sont en fait là aussi des variables réservées qui permettent pour certaines d'effectuer des traitements sur les paramètres eux-même. Ces paramètres sont les suivants :

$0

Contient le nom du script tel qu'il a été invoqué

$*

L'ensembles des paramètres sous la forme d'un seul argument

$@

L'ensemble des arguments, un argument par paramètre

$#

Le nombre de paramètres passés au script

$?

Le code retour de la dernière commande

$$

Le PID su shell qui exécute le script

$!

Le PID du dernier processus lancé en arrière-plan

Exemple 2

Voici un autre petit script mettant en oeuvre l'ensemble des paramètres spéciaux vus ci-dessus.

#!/bin/bash

# affiche_param_2.sh

 

# Affichage du nom su script

echo "Le nom de mon script est : $0"

# Affichage du nombre de paramètres

echo "Vous avez passé $# paramètres"

# Liste des paramètres (un seul argument)

for param in "$*"

do

 echo "Voici la liste des paramètres (un seul argument) : $param"

done

# Liste des paramètres (un paramètre par argument)

echo "Voici la liste des paramètres (un paramètre par argument) :"

for param in "$@"

do

 echo -e "      Paramètre : $param"

done

# Affichage du processus

echo "Le PID du shell qui exécute le script est : $$"

# Exécution d'une commande qui s'exécute en arrière-plan

sleep 100 &

# Affichage du processus lancé en arrière-plan

echo "Le PID de la dernière commande exécutée en arrière-plan est : $!"

# Affichage du code retour de la dernière commande "echo"

echo "Le code retour de la commande précédente est : $?"

# Génération d'une erreur

echo "Génération d'une erreur..."

# Affichage de la mauvaise commande

echo "ls /etc/password 2>/dev/null"

ls /etc/password 2>/dev/null

# Affichage du code retour de la dernière commande

echo "Le code retour de la commande précédente est : $?"

exit

Ce qui donne avec l'invocation suivante :

./affiche_param_2.sh 1 2 3 quatre 5 six

Le nom de mon script est : ./affiche_param_2.sh

Vous avez passé 6 paramètres

Voici la liste des paramètres (un seul argument) : 1 2 3 quatre 5 six

Voici la liste des paramètres (un paramètre par argument) :

        Paramètre : 1

        Paramètre : 2

        Paramètre : 3

        Paramètre : quatre

        Paramètre : 5

        Paramètre : six

Le PID du shell qui exécute le script est : 6165

Le PID de la dernière commande exécutée en arrière-plan est : 6166

Le code retour de la commande précédente est : 0

Génération d'une erreur...

ls /etc/password 2>/dev/null

Le code retour de la commande précédente est : 1

Initialiser des paramètres

- La commande "set" -

Il est possible d'affecter directement des paramètres au shell grâce à la commande

set

Une simple commande tel que :

set param1 param2 param3

initialisera automatiquement les paramètres positionnels

$1

,

$2

,

$3

avec les valeurs

param1

,

param2

,

param3

, effaçant de ce fait les anciennes valeurs si toutefois elles existaient. Les paramètres spéciaux

$#

,

$*

et

$@

sont automatiquement mis à jours en conséquence.

Exemples

$ set param1 param2 param3

$ echo "Nombre de paramètres : $#"

  Nombre de paramètres : 3

$ echo "Le second paramètre est : $2"

  Le second paramètre est : param2

$ echo "Les paramètres sont : $@"

  Les paramètres sont : param1 param2 param3

$ set pêche pomme

$ echo "Nombre de paramètres : $#"

  Nombre de paramètres : 2

$ echo "Les paramètres sont : $@"

  Les paramètres sont : pêche pomme

Cette fonctionnalité peut s'avérer utile dans le traitement de fichiers ligne
par ligne afin d'isoler chaque mot (champ), et d'en formater la sortie.

$ IFS=":"; set $(grep $USER /etc/passwd)

$ echo -e "Login :      $1

Nom :   $5

ID :    $3

Group : $4

Shell : $7"

Login : jp

Nom :   Jean-Philippe

ID :    500

Group : 500

Shell : /bin/bash

- La commande "shift" -

La commande interne

shift

permet quant à elle de décaler les paramètres. La valeur du 1er paramètre (

$1

) est remplacée par la valeur du 2nd paramètre (

$2

), celle du 2nd paramètre (

$2

) par celle du 3ème paramètre (

$3

), etc... On peut indiquer en argument (

shift [n]

) le nombre de pas (position) dont il faut décaler les paramètres.

Exemple 3

Voilà une mise en oeuvre de l'emploi de la commande interne "shift".

#!/bin/bash

# decale_param.sh

 

echo

echo "Nombre de paramètres : $#"

echo "Le 1er paramètre est : $1"

echo "Le 3ème paramètre est : $3"

echo "Le 6ème paramètre est : $6"

echo "Le 10ème paramètre est : ${10}"

echo "============================================="

echo "Décalage d'un pas avec la commande "shift""

shift

echo "Nombre de paramètres : $#"

echo "Le 1er paramètre est : $1"

echo "Le 3ème paramètre est : $3"

echo "Le 6ème paramètre est : $6"

echo "Le 10ème paramètre est : ${10}"

echo "============================================="

echo "Décalage de quatre pas avec la commande "shift 4""

shift 4

echo "Nombre de paramètres : $#"

echo "Le 1er paramètre est : $1"

echo "Le 3ème paramètre est : $3"

echo "Le 6ème paramètre est : $6"

echo "Le 10ème paramètre est : ${10}"

echo

Et son résultat :

./decale_param.sh 1 2 3 4 5 6 7 8 9 10

Nombre de paramètres : 10

Le 1er paramètre est : 1

Le 3ème paramètre est : 3

Le 6ème paramètre est : 6

Le 10ème paramètre est : 10

=============================================

Décalage d'un pas avec la commande "shift"

Nombre de paramètres : 9

Le 1er paramètre est : 2

Le 3ème paramètre est : 4

Le 6ème paramètre est : 7

Le 10ème paramètre est :

=============================================

Décalage de quatre pas avec la commande "shift 4"

Nombre de paramètres : 5

Le 1er paramètre est : 6

Le 3ème paramètre est : 8

Le 6ème paramètre est :

Le 10ème paramètre est :

Getopts

Ajouter des options avec getop

Voici à quoi ressemble la première étape :

OPTS=$( getopt -o h -l home,nb_fichiers: -- "$@" )

if [ $? != 0 ]

then

    exit 1

fi

 

eval set -- "$OPTS"

 

Ligne 1 :

Pour analyser les options, on utilise une boucle :

while true ; do

    case "$1" in

        -h) usage;

            exit 0;;

         --home) showHome;

                 shift;;

         --nb_fichiers) echo "Afficher le nombre de fichiers dans le répertoire $2";

                 shift 2;;

         --) shift; break;;

    esac

done

 

Analysons cette portion de code :

Le script final, de mon cru et sous licence GPL ;), pourra ainsi ressembler à ceci :

#!/bin/bash

 

function usage(){

 printf "Utilisation du script :\n"

 printf "\t--home                   : affiche le chemin vers le home de l'utilisateur courant ;\n"

 printf "\t--nb_fichiers repertoire : affiche le nombre de fichiers contenus dans le répertoire ;\n"

 printf "\t-h                       : affiche ce message.\n"

}

 

if [ $# -eq 0 ]

then

 usage

fi

 

function showHome(){

 echo "Home de l'utilisateur $USER";

 echo $HOME;

}

 

function nbFichiers(){

 if [ -d $1 ]

 then

  nb=$( ls $1 | wc -l )

  echo "$1 contient $nb fichiers et répertoires."

 else

  echo "Ce n'est pas un répertoire !"

  usage

  exit 0

 fi

}

 

OPTS=$( getopt -o h -l home,nb_fichiers: -- "$@" )

if [ $? != 0 ]

then

    exit 1

fi

 

eval set -- "$OPTS"

 

while true ; do

    case "$1" in

        -h) usage;

            exit 0;;

        --home) showHome;

                shift;;

 --nb_fichiers) echo "Afficher le nombre de fichiers et répertoires dans le répertoire $2";

  nbFichiers $2;

  shift 2;;

        --) shift; break;;

    esac

done

 

exit 0

contrôle les opérateurs utilisés par une commande

Getopts est une commande qui permet de contrôler les opérateurs utilisés par une commande. Cette méthode prendra en paramètre une chaîne de caractères lui indiquant les lettres définissant les options, et pourra être parcourue dans une boucle afin de contrôler chaque argument.

Pour illustrer son utilisation, imaginons un script qui accepte deux arguments : l'un avec l'option "v", qui peut être égale à 15 ou 75 l'autre avec l'option "g". On va créer une fonction "usage" qui affiche une phrase montrant l'utilisation du script :

usage() { echo "Usage: $0 [-v <15|75>] [-p <chaîne de caractères>]" 1>&2; exit 1; }

Pour vérifier les arguments de la fonction, on va utiliser "getopts". Dans la boucle, on utilise l'instruction "case" pour vérifier la valeur de l'option saisie. Pour l'option "g", on récupère la valeur de p dans une variable grâce à la variable "OPTARG". Pour "v", on contrôle que la valeur est égale à 15 ou 75. Si ce n'est pas le cas, on appelle la fonction "usage". Pour tous les autres arguments, on les détecte avec l'opérateur "*", et on appelle la fonction "*". On décale ensuite l'ordre des paramètres avec la commande "shift". Pour vérifier que tous les paramètres sont bien saisis, on réalise un test avec l'opérateur de comparaison "-z".

while getopts ":v:g:" option; do

    case "${option}" in

        v)

            v=${OPTARG}

            ((v == 15 || v == 75)) || usage

            ;;

        g)

            g=${OPTARG}

            ;;

        *)

            usage

            ;;

    esac

done

shift $((OPTIND-1))

if [ -z "${v}" ] || [ -z "${g}" ]; then

    usage

fi

echo "v = ${v}"

echo "g = ${g}"

Voici des exemples d'utilisation du script :

# Sans paramètres, le message d'usage est affiché

./monscript.sh

Usage: ./monscript.sh [-v <15|75>] [-g <chaîne de caractères>]

#Usage avec un mauvais paramètre

./myscript.sh -h 1

Usage: ./monscript.sh [-v <15|75>] [-g <chaîne de caractères>]

# usage correct

$ ./myscript.sh -v 15 -g toto

v = 15

g = toto